#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/time.h>

// 串口设备文件描述符
int serial_fd = -1;

// 配置串口参数
int configure_serial_port(int fd, speed_t baud_rate)
{
    struct termios tty;

    // 获取当前串口配置
    if (tcgetattr(fd, &tty) != 0)
    {
        perror("tcgetattr");
        return -1;
    }

    // 设置波特率
    cfsetispeed(&tty, baud_rate);
    cfsetospeed(&tty, baud_rate);

    // 设置数据位为8位
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;

    // 无奇偶校验
    tty.c_cflag &= ~PARENB;

    // 1个停止位
    tty.c_cflag &= ~CSTOPB;

    // 不使用流控制
    tty.c_cflag &= ~CRTSCTS;

    // 启用接收器，保持本地模式
    tty.c_cflag |= CREAD | CLOCAL;

    // 禁用规范模式和回显
    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO;
    tty.c_lflag &= ~ECHOE;
    tty.c_lflag &= ~ISIG;

    // 禁用软件流控制
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);

    // 禁用输出处理
    tty.c_oflag &= ~OPOST;
    tty.c_oflag &= ~ONLCR;

    // 设置超时和最小字符数
    tty.c_cc[VTIME] = 1; // 等待字符的超时时间（单位0.1秒）
    tty.c_cc[VMIN] = 0;  // 最小接收字符数

    // 清空输入输出缓冲区
    tcflush(fd, TCIOFLUSH);

    // 应用新配置
    if (tcsetattr(fd, TCSANOW, &tty) != 0)
    {
        perror("tcsetattr");
        return -1;
    }

    return 0;
}

// 发送单个字节数据
int send_byte(int fd, unsigned char data)
{
    ssize_t bytes_written = write(fd, &data, 1);
    if (bytes_written != 1)
    {
        perror("write");
        return -1;
    }
    // 确保数据发送完成
    tcdrain(fd);
    return 0;
}

// 检查是否有数据可读（使用轮询方式）
int check_data_available(int fd)
{
    fd_set read_fds;
    struct timeval timeout;

    FD_ZERO(&read_fds);
    FD_SET(fd, &read_fds);

    // 设置超时时间为0.1秒
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000;

    int result = select(fd + 1, &read_fds, NULL, NULL, &timeout);
    if (result < 0)
    {
        perror("select");
        return -1;
    }

    return (result > 0 && FD_ISSET(fd, &read_fds)) ? 1 : 0;
}

// 读取所有可用数据
int read_available_data(int fd)
{
    unsigned char buffer[256];
    ssize_t bytes_read;

    // 使用非阻塞方式读取数据
    bytes_read = read(fd, buffer, sizeof(buffer));
    if (bytes_read > 0)
    {
        printf("Received %zd bytes: ", bytes_read);
        for (int i = 0; i < bytes_read; i++)
        {
            if (buffer[i] >= 32 && buffer[i] <= 126)
            {
                // 可打印字符
                printf("'%c' (0x%02X) ", buffer[i], buffer[i]);
            }
            else
            {
                // 不可打印字符
                printf("0x%02X ", buffer[i]);
            }
        }
        printf("\n");
        fflush(stdout);
        return bytes_read;
    }
    else if (bytes_read < 0)
    {
        if (errno != EAGAIN && errno != EWOULDBLOCK)
        {
            perror("read");
            return -1;
        }
    }

    return 0;
}

// 主线程函数
void *serial_thread(void *arg)
{
    unsigned char send_data = 0x41; // 发送字符 'A'
    int counter = 0;

    printf("Serial thread started. Sending and receiving data...\n");

    while (1)
    {
        // 每秒发送一次数据
        printf("Sending data: ");
        if (send_data >= 32 && send_data <= 126)
        {
            printf("'%c' (0x%02X)\n", send_data, send_data);
        }
        else
        {
            printf("0x%02X\n", send_data);
        }

        if (send_byte(serial_fd, send_data) < 0)
        {
            printf("Failed to send data\n");
        }
        send_data++;
        if (send_data > 0x5A)
        { // 限制在A-Z范围内
            send_data = 0x41;
        }

        // 检查并读取所有可用数据
        int bytes_received = 0;
        do
        {
            bytes_received = read_available_data(serial_fd);
            if (bytes_received > 0)
            {
                printf("Data received successfully\n");
            }
            else if (bytes_received < 0)
            {
                printf("Error reading data\n");
                break;
            }
            // 如果有数据，继续检查是否还有更多数据
            if (bytes_received > 0)
            {
                usleep(10000); // 等待10ms再检查
            }
        } while (bytes_received > 0);

        if (bytes_received == 0)
        {
            printf("No data received\n");
        }

        // 等待1秒
        sleep(1);
        counter++;

        // 每10次循环打印一次提示信息
        if (counter % 10 == 0)
        {
            printf("--- %d seconds passed ---\n", counter);
        }
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t thread_id;
    const char *serial_device = "/dev/ttyS4"; // 默认串口设备
    speed_t baud_rate = B115200;              // 默认波特率

    // 检查命令行参数
    if (argc > 1)
    {
        serial_device = argv[1];
    }
    if (argc > 2)
    {
        int baud = atoi(argv[2]);
        switch (baud)
        {
        case 9600:
            baud_rate = B9600;
            break;
        case 19200:
            baud_rate = B19200;
            break;
        case 38400:
            baud_rate = B38400;
            break;
        case 57600:
            baud_rate = B57600;
            break;
        case 115200:
            baud_rate = B115200;
            break;
        default:
            printf("Unsupported baud rate, using 115200\n");
            baud_rate = B115200;
            break;
        }
    }

    // 打开串口设备
    serial_fd = open(serial_device, O_RDWR | O_NOCTTY);
    if (serial_fd < 0)
    {
        perror("open");
        printf("Failed to open serial device %s\n", serial_device);
        return 1;
    }

    printf("Opened serial device %s\n", serial_device);

    // 配置串口
    if (configure_serial_port(serial_fd, baud_rate) < 0)
    {
        printf("Failed to configure serial port\n");
        close(serial_fd);
        return 1;
    }

    printf("Configured serial port with baud rate %d\n",
           (baud_rate == B9600) ? 9600 : (baud_rate == B19200) ? 19200
                                     : (baud_rate == B38400)   ? 38400
                                     : (baud_rate == B57600)   ? 57600
                                                               : 115200);

    // 创建线程处理串口通信
    if (pthread_create(&thread_id, NULL, serial_thread, NULL) != 0)
    {
        perror("pthread_create");
        close(serial_fd);
        return 1;
    }

    printf("Serial communication thread started...\n");
    printf("Press Ctrl+C to exit\n");

    // 等待线程结束
    pthread_join(thread_id, NULL);

    // 关闭串口设备
    close(serial_fd);
    printf("Serial device closed\n");

    return 0;
}